﻿using LxBasic;

namespace LxCore
{
    public class ScalarFinderBase<T> : FieldBase<T>
    {
        protected IField<T>? _Field;
        public IField<T>? Field => _Field;
        public override bool IsParameter(out T value)
        {
            if (Field == null)
            {
                return base.IsParameter(out value);
            }
            else
            {
                return Field.IsParameter(out value);
            }
        }
        public override ICellVarArr<T>? GetCellVarArr(IIndexHost indexHost)
        {
            return Field?.GetCellVarArr(indexHost);
        }
        public override IFaceVarArr<T>? GetFaceVarArr(IIndexHost indexHost)
        {
            return Field?.GetFaceVarArr(indexHost);
        }
    }
    public class VectorFinder : ScalarFinderBase<Vector3d>
    {
        public VectorFinder(VectorFieldTypes scalarType)
        {
            this.VectorType = scalarType;
        }
        private VectorFieldTypes _VectorType;
        public VectorFieldTypes VectorType
        {
            get => _VectorType;
            set
            {
                _VectorType = value;
                //TODO 同时从SystemFieldCenter查找对应的Field,设置到Field变量上
                var sysf = LxSim.Sim.Definitions.SystemField;
                _Field = value switch
                {
                    VectorFieldTypes.Velocity => sysf.Velocity,
                    _ => null,
                };
            }
        }
    }
    public class ScalarFieldFinder : ScalarFinderBase<double>
    {
        public ScalarFieldFinder(ScalarFieldTypes scalarType)
        {
            ScalarType = scalarType;
        }
        private ScalarFieldTypes _ScalarType;
        public ScalarFieldTypes ScalarType
        {
            get => _ScalarType;
            set
            {
                _ScalarType = value;
                var sysf = LxSim.Sim.Definitions.SystemField;
                _Field = value switch
                {
                    ScalarFieldTypes.Temperature => sysf.Temperature,
                    ScalarFieldTypes.Velocity => sysf.VelocityMagnitude,
                    ScalarFieldTypes.Vel_U => sysf.Velocity_U,
                    ScalarFieldTypes.Vel_V => sysf.Velocity_V,
                    ScalarFieldTypes.Vel_W => sysf.Velocity_W,
                    ScalarFieldTypes.Pressure => sysf.Pressure,
                    ScalarFieldTypes.Density => sysf.Density,
                    ScalarFieldTypes.MassImbalance => sysf.MassImbalance,
                    ScalarFieldTypes.BoundAdjacentCellIndex => sysf.BoundAdjacentCellIndex,
                    ScalarFieldTypes.BoundAdjacentCellPressure => sysf.BoundAdjacentCellPressure,
                    _ => null,
                };
            }
        }
    }
}
//public override ICellVarArr<Vector3d>? GetCellVarArr(IIndexHost indexHost)
//{
//    FvZone z = GetZone(indexHost);
//    ZoneCFDFields zf = ResHelper.GetField(z);
//    switch (VectorType)
//    {
//        case VectorFieldTypes.Velocity: return indexHost is FvInner ? zf.Velocity?.GetInnCellVelVars() : zf.Velocity?.GetBouCellVelVars();
//        default: throw new NotImplementedException();
//    }
//}
//public override IFaceVarArr<Vector3d>? GetFaceVarArr(IIndexHost indexHost)
//{
//    FvZone z = GetZone(indexHost);
//    ZoneCFDFields zf = ResHelper.GetField(z);
//    switch (VectorType)
//    {
//        case VectorFieldTypes.Velocity: return velocity();
//        default: throw new NotImplementedException();
//    }
//    IFaceVarArr<Vector3d> velocity()
//    {
//        var vel = zf.Velocity;
//        if (vel == null) return null;
//        switch (indexHost)
//        {
//            case FvInner inn: return new VarArrBuilder3.InnFaceAve(z, vel.U.InnX, vel.V.InnX, vel.W.InnX);
//            case FvBound bou: return new VarArrBuilder3.DirectFaceVars(vel.U.BouX, vel.V.BouX, vel.W.BouX);
//            default: return null;
//        }
//    }
//}


//private (ICellVarArr<double>? CellVarArr, IFaceVarArr<double>? FaceVarArr) GetVarArr(Func<ZoneCFDFields, ScalarBase> path, IIndexHost indexHost, VarPosTypes varPos)
//{
//    ScalarBase scalar1;
//    switch (indexHost, varPos)
//    {
//        case (FvInner inner, VarPosTypes.OnCell):
//            scalar1 = path.Invoke(ResHelper.GetField(inner.InZone));
//            return (scalar1 == null ? null : new VarArrBuider.Direct<double>(scalar1.InnX), null);
//        case (FvInner inner, VarPosTypes.OnFace):
//            scalar1 = path.Invoke(ResHelper.GetField(inner.InZone));
//            return (null, scalar1 == null ? null : new VarArrBuider.InnFaceByAve(inner.InZone, scalar1.InnX));
//        case (FvBound bound, VarPosTypes.OnCell):
//            scalar1 = path.Invoke(ResHelper.GetField(bound.InZone));
//            return (scalar1 == null ? null : new VarArrBuider.Direct<double>(scalar1.BouX), null);
//        case (FvBound bound, VarPosTypes.OnFace):
//            scalar1 = path.Invoke(ResHelper.GetField(bound.InZone));
//            return (null, scalar1 == null ? null : new VarArrBuider.Direct<double>(scalar1.BouX));
//        //case FvJoint joint:
//        //    break;
//        default: return (null, null);
//    }
//}
//private (ICellVarArr<double>? CellVarArr, IFaceVarArr<double>? FaceVarArr) GetVarArr(IIndexHost indexHost, VarPosTypes varPos)
//{
//    switch (ScalarType)
//    {
//        case ScalarFieldTypes.Temperature: return GetVarArr(zf => zf.Temperature, indexHost, varPos);
//        case ScalarFieldTypes.Vel_U: return GetVarArr(zf => zf.Velocity?.U, indexHost, varPos);
//        case ScalarFieldTypes.Vel_V: return GetVarArr(zf => zf.Velocity?.V, indexHost, varPos);
//        case ScalarFieldTypes.Vel_W: return GetVarArr(zf => zf.Velocity?.W, indexHost, varPos);
//        case ScalarFieldTypes.Pressure: return GetVarArr(zf => zf.Pressure, indexHost, varPos);
//        case ScalarFieldTypes.BoundAdjacentCellIndex: return new BoundAdjacentCellIndex();
//        case ScalarFieldTypes.Velocity: return new VelocityMagnitudeField();
//        case ScalarFieldTypes.MassImbalance: return GetMassImbalanceVarArr(indexHost, varPos);
//        case ScalarFieldTypes.BoundAdjacentCellPressure: return new BoundAdjacentCellPressure();
//        default:
//            return (null, null);
//    }
//}
//private (ICellVarArr<double>? CellVarArr, IFaceVarArr<double>? FaceVarArr) GetMassImbalanceVarArr(IIndexHost indexHost, VarPosTypes varPos)
//{
//    MassFluxBase mf;
//    bool getScalar(FvZone zone, out MassFluxBase massflux)
//    {
//        massflux = ResHelper.GetField(zone).MassFlux;
//        return massflux != null;
//    }
//    switch (indexHost, varPos)
//    {
//        case (FvInner inn, VarPosTypes.OnCell):
//            return (getScalar(inn.InZone, out mf) ? new VarArrBuider.Direct<double>(mf.MassImbalance) : null, null);
//        case (FvInner inn, VarPosTypes.OnFace):
//            return (null, getScalar(inn.InZone, out mf) ? new VarArrBuider.InnFaceByAve(inn.InZone, mf.MassImbalance) : null);
//        case (FvBound bou, VarPosTypes.OnCell):
//            return (getScalar(bou.InZone, out mf) ? new VarArrBuider.BouCellFaceByInn<double>(bou.InZone, mf.MassImbalance) : null, null);
//        case (FvBound bou, VarPosTypes.OnFace):
//            return (null, getScalar(bou.InZone, out mf) ? new VarArrBuider.BouCellFaceByInn<double>(bou.InZone, mf.MassImbalance) : null);
//        default: return (null, null);
//    }
//}
//public override ICellVarArr<double>? GetCellVarArr(IIndexHost indexHost)
//{
//    return GetVarArr(indexHost, VarPosTypes.OnCell).CellVarArr;
//}
//public override IFaceVarArr<double>? GetFaceVarArr(IIndexHost indexHost)
//{
//    return GetVarArr(indexHost, VarPosTypes.OnFace).FaceVarArr;
//}
//public enum FieldPosTypes : byte
//{
//    OnInner,
//    OnBound,
//    OnJoint
//}
//public enum VarPosTypes : byte
//{
//    OnCell,
//    OnFace,
//    //OnEdge,
//    //OnNode,
//}